<?php

namespace App\Http\Controllers;

use App\Models\AffiliateLog;
use App\Models\BonusPoolRecord;
use App\Models\IntegralLog;
use App\Models\User;
use App\Models\UserLevel;
use App\Utility\PayfastUtility;
use Illuminate\Http\Request;
use App\Models\Category;
use App\Models\Cart;
use App\Models\Order;
use App\Models\Coupon;
use App\Models\CouponUsage;
use App\Models\Address;
use App\Models\CombinedOrder;
use App\Models\Product;
use App\Utility\PayhereUtility;
use App\Utility\NotificationUtility;
use Illuminate\Support\Facades\DB;
use Session;
use Auth;

class CheckoutController extends Controller
{

    public function __construct()
    {
        //
    }

    //check the selected payment gateway and redirect to that controller accordingly
    public function checkout(Request $request)
    {
        // Minumum order amount check
        if (get_setting('minimum_order_amount_check') == 1) {
            $subtotal = 0;
            foreach (Cart::where('user_id', Auth::user()->id)->get() as $key => $cartItem) {
                $product = Product::find($cartItem['product_id']);
                $subtotal += cart_product_price($cartItem, $product, false, false) * $cartItem['quantity'];
            }
            if ($subtotal < get_setting('minimum_order_amount')) {
                flash(translate('You order amount is less then the minimum order amount'))->warning();
                return redirect()->route('home');
            }
        }
        // Minumum order amount check end

        if ($request->payment_option != null) {
            (new OrderController)->store($request);

            $request->session()->put('payment_type', 'cart_payment');

            $data['combined_order_id'] = $request->session()->get('combined_order_id');
            $request->session()->put('payment_data', $data);
            if ($request->session()->get('combined_order_id') != null) {

                // If block for Online payment, wallet and cash on delivery. Else block for Offline payment
                $decorator = __NAMESPACE__ . '\\Payment\\' . str_replace(' ', '', ucwords(str_replace('_', ' ', $request->payment_option))) . "Controller";
                if (class_exists($decorator)) {
                    return (new $decorator)->pay($request);
                } else {
                    $combined_order = CombinedOrder::findOrFail($request->session()->get('combined_order_id'));
                    foreach ($combined_order->orders as $order) {
                        $order->manual_payment = 1;
                        $order->save();
                    }
                    flash(translate('Your order has been placed successfully. Please submit payment information from purchase history'))->success();
                    return redirect()->route('order_confirmed');
                }
            }
        } else {
            flash(translate('Select Payment Option.'))->warning();
            return back();
        }
    }

    //redirects to this method after a successfull checkout
    public function checkout_done($combined_order_id, $payment)
    {
        $combined_order = CombinedOrder::findOrFail($combined_order_id);

        foreach ($combined_order->orders as $key => $order) {
            $order = Order::findOrFail($order->id);
            $order->payment_status = 'paid';
            $order->payment_details = $payment;
            $order->save();

//            calculateCommissionAffilationClubPoint($order);
            $this->calculateCommission($order);
        }
        Session::put('combined_order_id', $combined_order_id);
        return redirect()->route('order_confirmed');
    }

    public function calculateCommission($order)
    {
        if($order['deduction_integral']){
            IntegralLog::insert([
                'user_id' => $order['user_id'],
                'number' => $order['deduction_integral'],
                'order_id' => $order['id'],
                'type' => 4,
                'pm' => 0,
            ]);
            User::where('id',$order['user_id'])->decrement('integral',$order['deduction_integral']);
        }
        $user = User::where('id',$order['user_id'])->first();

        $ld_zt_uid = 0;
        $ld_jd_uid = 0;
        $ld_pj_uid = 0;
        $ld_zt_money = 0;
        $ld_jd_money = 0;
        $ld_pj_money = 0;
        $product_type = 0;
        $jc_arr = [];
        $upgrade_level = 0;
        $total_commission = 0;
        $parentList = $this->getParentsByUserId($order['user_id']);
        $gift_points = 0;
        foreach ($order->orderDetails as $key => $orderDetail) {
            $product = Product::where('id',$orderDetail['product_id'])->first();
            $gift_points += $product->gift_points;
            $upgrade_level = $product->upgrade_level;
            if($product->product_type == 1){
                $product_type = 1;
            }
            if($product->product_type == 0){
                $paward_value = json_decode($product->paward_value,true);
                $al = 0;

                foreach ($parentList as $k => $value){
//                    if($k == 0){
                        $award = round($orderDetail['price'] * ($paward_value[$user->level]['jc'][$value->level]/100),2);

                        $cha = $award - $al;
                        if($cha){
                            $sj_user = User::where('id',$value['pid'])->first();
                            $pj_money = 0;
                            $pj_uid = 0;
                            if($sj_user){
                                if($sj_user->level == $value['level']){
                                    $pj_money = round($cha * ($paward_value[$user->level]['pj']/100),2);
                                    $pj_uid = $sj_user->id;
                                }
                            }

                            $jc_arr[] = [
                                'user_id' => $value['id'],
                                'money' => $cha,
                                'pj_uid' => $pj_uid,
                                'pj_money' => $pj_money,
                            ];
                        }
                        $al = $award;
//                    }
                    if($upgrade_level == 1){
                        break;
                    }
                }
            }else{
                if($user['pid']){
                    $jaward_value = json_decode($product->jaward_value,true);
                    $boss_id = $this->getUserLdSpread($order['user_id']);
                    $one_user = User::where('id',$user['pid'])->first();
                    $ld_zt_uid = $one_user->id;
//                    dump($one_user->cybt_num);
//                    dump($upgrade_level);

                    if($one_user->cybt_num > 0 && $upgrade_level == 10){
                        $level_info = UserLevel::where('id',$one_user->level)->first();
//                        dump($level_info['cybt_rate']);
                        $ld_zt_money = round($orderDetail['price'] * ($level_info['cybt_rate']/100),2);
//                        dump($ld_zt_money);
                        User::where('id',$ld_zt_uid)->decrement('cybt_num',1);
                    }else{
//                        dump($one_user->level);
                        if($one_user && isset($jaward_value[$one_user->level]['zt'])){
                            $ld_zt_money += $jaward_value[$one_user->level]['zt'];
                        }
//                        dump($ld_zt_money);
                        if($one_user['id'] == $boss_id){
                            $ld_zt_money += $jaward_value[$one_user->level]['jd'];
                        }else{
                            $ld_jd_uid = $boss_id;
                            $ld_jd_money = 0;
                            if($boss_id){
                                $boss_user = User::where('id',$boss_id)->first();
                                $ld_jd_money = $jaward_value[$boss_user->level]['jd'];
                            }
                        }
//                        dump($boss_id);
//                        dump($ld_jd_money);
                        if($one_user && isset($jaward_value[$one_user->level]['zt'])){
                            $two_user = User::where('id',$one_user['pid'])->first();
                            if($two_user && $two_user->identity == $one_user->identity){
                                $ld_pj_uid = $two_user->id;
//                                $ld_pj_money = round($ld_zt_money * ($jaward_value[$one_user->level]['pj']/100),2);
                                $ld_pj_money = $jaward_value[$one_user->level]['pj'];
                            }
                        }
                    }
                }


            }

            //奖金池
            if($product->bonus_pool){
                $bonus_pool = json_decode($product->bonus_pool,true);
                foreach ($bonus_pool as $key => $pool){
                    BonusPoolRecord::insert([
                        'uid' => $order['user_id'],
                        'pool_id' => $key,
                        'stage' => date('Ym'),
                        'product_id' => $orderDetail['product_id'],
                        'order_id' => $order['id'],
                        'order_sn' => $order['code'],
                        'enter_amount' => round($orderDetail['price'] * ($pool/100),2),
                        'created_at' => date('Y-m-d H:i:s'),
                        'updated_at' => date('Y-m-d H:i:s'),
                    ]);
                }
            }
        }

        //赠送积分
        if($gift_points){
            IntegralLog::insert([
                'user_id' => $order['user_id'],
                'number' => $gift_points,
                'order_id' => $order['id'],
                'type' => 1,
                'pm' => 1,
            ]);
            User::where('id',$order['user_id'])->increment('integral',$gift_points);
        }


        //分佣
        if($ld_zt_uid && $ld_zt_money){
            $child_list = User::where('pid',$ld_zt_uid)->orderBy('up_agent_time', 'asc')->limit(2)->get();
            $boss_count = 0;
            foreach ($child_list as $val){
                if($val['identity'] == 20){
                    $boss_count += 1;
                }
            }
            $freeze_funds = 0;
            $rate = get_setting('frozen_funds_rate');
            if($boss_count < get_setting('frozen_funds_limit')){
                $freeze_funds = round($ld_zt_money * $rate/100,2);
                $ld_zt_money = $ld_zt_money - round($ld_zt_money * $rate/100,2);
            }

            AffiliateLog::insert([
                'user_id' => $order['user_id'],
                'referred_by_user' => $ld_zt_uid,
                'amount' => $ld_zt_money,
                'freeze_funds' => $freeze_funds,
                'order_id' => $order['id'],
                'affiliate_type' => 'ld_zt',
                'status' => 1,
            ]);
            User::where('id',$ld_zt_uid)->increment('balance',$ld_zt_money);
            User::where('id',$ld_zt_uid)->increment('freeze_funds',$freeze_funds);
            $total_commission += $ld_zt_money+$freeze_funds;
        }

        if($ld_jd_uid && $ld_jd_money){

            $child_list = User::where('pid',$ld_jd_uid)->orderBy('up_agent_time', 'asc')->limit(2)->get();
            $boss_count = 0;
            foreach ($child_list as $val){
                if($val['identity'] == 20){
                    $boss_count += 1;
                }
            }
            $freeze_funds = 0;
            $rate = get_setting('frozen_funds_rate');
            if($boss_count < get_setting('frozen_funds_limit')){
                $freeze_funds = round($ld_jd_money * $rate/100,2);
                $ld_jd_money = $ld_jd_money - round($ld_jd_money * $rate/100,2);
            }

            AffiliateLog::insert([
                'user_id' => $order['user_id'],
                'referred_by_user' => $ld_jd_uid,
                'amount' => $ld_jd_money,
                'freeze_funds' => $freeze_funds,
                'order_id' => $order['id'],
                'affiliate_type' => 'ld_jd',
                'status' => 1,
            ]);
            User::where('id',$ld_jd_uid)->increment('balance',$ld_jd_money);
            User::where('id',$ld_jd_uid)->increment('freeze_funds',$freeze_funds);
            $total_commission += $ld_jd_money+$freeze_funds;
        }
        if($ld_pj_uid && $ld_pj_money){
            $child_list = User::where('pid',$ld_pj_uid)->orderBy('up_agent_time', 'asc')->limit(2)->get();
            $boss_count = 0;
            foreach ($child_list as $val){
                if($val['identity'] == 20){
                    $boss_count += 1;
                }
            }
            $freeze_funds = 0;
            $rate = get_setting('frozen_funds_rate');
            if($boss_count < get_setting('frozen_funds_limit')){
                $freeze_funds = round($ld_pj_money * $rate/100,2);
                $ld_pj_money = $ld_pj_money - round($ld_pj_money * $rate/100,2);
            }

            AffiliateLog::insert([
                'user_id' => $order['user_id'],
                'referred_by_user' => $ld_pj_uid,
                'amount' => $ld_pj_money,
                'freeze_funds' => $freeze_funds,
                'order_id' => $order['id'],
                'affiliate_type' => 'ld_pj',
                'status' => 1,
            ]);
            User::where('id',$ld_pj_uid)->increment('balance',$ld_pj_money);
            User::where('id',$ld_pj_uid)->increment('freeze_funds',$freeze_funds);
            $total_commission += $ld_pj_money+$freeze_funds;
        }
        if($jc_arr){
            foreach ($jc_arr as $jc){
                if($jc['money'] > 0){
                    AffiliateLog::insert([
                        'user_id' => $order['user_id'],
                        'referred_by_user' => $jc['user_id'],
                        'amount' => $jc['money'],
                        'order_id' => $order['id'],
                        'affiliate_type' => 'pt_jc',
                        'status' => 1,
                    ]);
                    User::where('id',$jc['user_id'])->increment('balance',$jc['money']);
                    $total_commission += $jc['money'];
                }
                if($jc['pj_uid'] && $jc['pj_money'] > 0){
                    AffiliateLog::insert([
                        'user_id' => $order['user_id'],
                        'referred_by_user' => $jc['pj_uid'],
                        'amount' => $jc['pj_money'],
                        'order_id' => $order['id'],
                        'affiliate_type' => 'pt_pj',
                        'status' => 1,
                    ]);
                    User::where('id',$jc['pj_uid'])->increment('balance',$jc['pj_money']);
                    $total_commission += $jc['pj_money'];
                }
            }
        }
        if($total_commission){
            Order::where('id',$order['id'])->update(['commission_calculated' => $total_commission]);
        }
        //升级代理
//        if($product_type){
            if($upgrade_level){
                $level_info = UserLevel::where('id',$upgrade_level)->first();
                if($user->level < $upgrade_level){
                    $user->level = $upgrade_level;
                    $user->identity = $level_info['identity'];
                    if($upgrade_level == 10){
                        $user->up_agent_time = time();
                    }
                    $user->save();
                    //新增创业补贴数量
                    if($level_info['cybt_num'] > 0){
                        User::where('id',$user->id)->increment('cybt_num',$level_info['cybt_num']);
                    }
                }
                //升级老板
                if($upgrade_level == 10) {
                    foreach ($parentList as $parent) {
                        if ($parent['level'] == 10) {
                            //是否有两个直推代理
                            $agent_level = User::where('pid', $parent['id'])->whereIn('identity', [10, 20])->get();
                            if (count($agent_level) >= 2) {
                                User::where('id', $parent['id'])->update(['level' => 20, 'identity' => 20]);

                                //找上级，是否应该释放冻结基金
                                if($parent['pid']){
                                    $pr = User::where('id',$parent['pid'])->first();
                                    if($pr['level'] == 20 && $pr['freeze_funds'] > 0){
                                        $child_list = User::where('pid',$parent['pid'])->orderBy('up_agent_time', 'asc')->limit(2)->get();
                                        $boss_count = 0;
                                        foreach ($child_list as $val){
                                            if($val['identity'] == 20){
                                                $boss_count += 1;
                                            }
                                        }

                                        if($boss_count >= get_setting('frozen_funds_limit')){
                                            AffiliateLog::insert([
                                                'user_id' => $parent['pid'],
                                                'referred_by_user' => $parent['pid'],
                                                'amount' => $pr['freeze_funds'],
                                                'freeze_funds' => $pr['freeze_funds'] * -1,
                                                'order_id' => 0,
                                                'affiliate_type' => 'release',
                                                'status' => 1,
                                            ]);
                                            User::where('id',$parent['pid'])->increment('balance',$pr['freeze_funds']);
                                            User::where('id',$parent['pid'])->decrement('freeze_funds',$pr['freeze_funds']);
                                        }
                                    }

                                }
                            }
                        }
                    }
                }
            }
//        }
    }

    public function get_shipping_info(Request $request)
    {
        $carts = Cart::where('user_id', Auth::user()->id)->get();
//        if (Session::has('cart') && count(Session::get('cart')) > 0) {
        if ($carts && count($carts) > 0) {
            $categories = Category::all();
            return view('frontend.shipping_info', compact('categories', 'carts'));
        }
        flash(translate('Your cart is empty'))->success();
        return back();
    }

    public function store_shipping_info(Request $request)
    {
        if ($request->address_id == null) {
            flash(translate("Please add shipping address"))->warning();
            return back();
        }

        $carts = Cart::where('user_id', Auth::user()->id)->get();

        foreach ($carts as $key => $cartItem) {
            $cartItem->address_id = $request->address_id;
            $cartItem->save();
        }

        return view('frontend.delivery_info', compact('carts'));
        // return view('frontend.payment_select', compact('total'));
    }

    public function store_delivery_info(Request $request)
    {

        $carts = Cart::where('user_id', Auth::user()->id)
            ->get();

        if ($carts->isEmpty()) {
            flash(translate('Your cart is empty'))->warning();
            return redirect()->route('home');
        }

        $shipping_info = Address::where('id', $carts[0]['address_id'])->first();
        $total = 0;
        $tax = 0;
        $shipping = 0;
        $subtotal = 0;

        if ($carts && count($carts) > 0) {
            foreach ($carts as $key => $cartItem) {
                $product = Product::find($cartItem['product_id']);
                $tax += cart_product_tax($cartItem, $product, false) * $cartItem['quantity'];
                $subtotal += cart_product_price($cartItem, $product, false, false) * $cartItem['quantity'];

                if ($request['shipping_type_' . $product->user_id] == 'pickup_point') {
                    $cartItem['shipping_type'] = 'pickup_point';
                    $cartItem['pickup_point'] = $request['pickup_point_id_' . $product->user_id];
                } else {
                    $cartItem['shipping_type'] = 'home_delivery';
                }
                $cartItem['shipping_cost'] = 0;
                if ($cartItem['shipping_type'] == 'home_delivery') {
                    $cartItem['shipping_cost'] = getShippingCost($carts, $key);
                }

                if (isset($cartItem['shipping_cost']) && is_array(json_decode($cartItem['shipping_cost'], true))) {

                    foreach (json_decode($cartItem['shipping_cost'], true) as $shipping_region => $val) {
                        if ($shipping_info['city'] == $shipping_region) {
                            $cartItem['shipping_cost'] = (double)($val);
                            break;
                        } else {
                            $cartItem['shipping_cost'] = 0;
                        }
                    }
                } else {
                    if (!$cartItem['shipping_cost'] ||
                        $cartItem['shipping_cost'] == null ||
                        $cartItem['shipping_cost'] == 'null') {

                        $cartItem['shipping_cost'] = 0;
                    }
                }

                $shipping += $cartItem['shipping_cost'];
                $cartItem->save();

            }
            $total = $subtotal + $tax + $shipping;
            $tpwd = Auth::user()->tpwd;
            return view('frontend.payment_select', compact('carts', 'shipping_info', 'total', 'tpwd'));

        } else {
            flash(translate('Your Cart was empty'))->warning();
            return redirect()->route('home');
        }
    }

    public function apply_coupon_code(Request $request)
    {
        $coupon = Coupon::where('code', $request->code)->first();
        $response_message = array();

        if ($coupon != null) {
            if (strtotime(date('d-m-Y')) >= $coupon->start_date && strtotime(date('d-m-Y')) <= $coupon->end_date) {
                if (CouponUsage::where('user_id', Auth::user()->id)->where('coupon_id', $coupon->id)->first() == null) {
                    $coupon_details = json_decode($coupon->details);

                    $carts = Cart::where('user_id', Auth::user()->id)
                        ->where('owner_id', $coupon->user_id)
                        ->get();

                    $coupon_discount = 0;

                    if ($coupon->type == 'cart_base') {
                        $subtotal = 0;
                        $tax = 0;
                        $shipping = 0;
                        foreach ($carts as $key => $cartItem) {
                            $product = Product::find($cartItem['product_id']);
                            $subtotal += cart_product_price($cartItem, $product, false, false) * $cartItem['quantity'];
                            $tax += cart_product_tax($cartItem, $product, false) * $cartItem['quantity'];
                            $shipping += $cartItem['shipping_cost'];
                        }
                        $sum = $subtotal + $tax + $shipping;
                        if ($sum >= $coupon_details->min_buy) {
                            if ($coupon->discount_type == 'percent') {
                                $coupon_discount = ($sum * $coupon->discount) / 100;
                                if ($coupon_discount > $coupon_details->max_discount) {
                                    $coupon_discount = $coupon_details->max_discount;
                                }
                            } elseif ($coupon->discount_type == 'amount') {
                                $coupon_discount = $coupon->discount;
                            }

                        }
                    } elseif ($coupon->type == 'product_base') {
                        foreach ($carts as $key => $cartItem) {
                            $product = Product::find($cartItem['product_id']);
                            foreach ($coupon_details as $key => $coupon_detail) {
                                if ($coupon_detail->product_id == $cartItem['product_id']) {
                                    if ($coupon->discount_type == 'percent') {
                                        $coupon_discount += (cart_product_price($cartItem, $product, false, false) * $coupon->discount / 100) * $cartItem['quantity'];
                                    } elseif ($coupon->discount_type == 'amount') {
                                        $coupon_discount += $coupon->discount * $cartItem['quantity'];
                                    }
                                }
                            }
                        }
                    }

                    if ($coupon_discount > 0) {
                        Cart::where('user_id', Auth::user()->id)
                            ->where('owner_id', $coupon->user_id)
                            ->update(
                                [
                                    'discount' => $coupon_discount / count($carts),
                                    'coupon_code' => $request->code,
                                    'coupon_applied' => 1
                                ]
                            );
                        $response_message['response'] = 'success';
                        $response_message['message'] = translate('Coupon has been applied');
                    } else {
                        $response_message['response'] = 'warning';
                        $response_message['message'] = translate('This coupon is not applicable to your cart products!');
                    }

                } else {
                    $response_message['response'] = 'warning';
                    $response_message['message'] = translate('You already used this coupon!');
                }
            } else {
                $response_message['response'] = 'warning';
                $response_message['message'] = translate('Coupon expired!');
            }
        } else {
            $response_message['response'] = 'danger';
            $response_message['message'] = translate('Invalid coupon!');
        }

        $carts = Cart::where('user_id', Auth::user()->id)
            ->get();
        $shipping_info = Address::where('id', $carts[0]['address_id'])->first();

        $returnHTML = view('frontend.partials.cart_summary', compact('coupon', 'carts', 'shipping_info'))->render();
        return response()->json(array('response_message' => $response_message, 'html' => $returnHTML));
    }

    public function remove_coupon_code(Request $request)
    {
        Cart::where('user_id', Auth::user()->id)
            ->update(
                [
                    'discount' => 0.00,
                    'coupon_code' => '',
                    'coupon_applied' => 0
                ]
            );

        $coupon = Coupon::where('code', $request->code)->first();
        $carts = Cart::where('user_id', Auth::user()->id)
            ->get();

        $shipping_info = Address::where('id', $carts[0]['address_id'])->first();

        return view('frontend.partials.cart_summary', compact('coupon', 'carts', 'shipping_info'));
    }

    public function apply_club_point(Request $request)
    {
        if (addon_is_activated('club_point')) {

            $point = $request->point;

            if (Auth::user()->point_balance >= $point) {
                $request->session()->put('club_point', $point);
                flash(translate('Point has been redeemed'))->success();
            } else {
                flash(translate('Invalid point!'))->warning();
            }
        }
        return back();
    }

    public function remove_club_point(Request $request)
    {
        $request->session()->forget('club_point');
        return back();
    }

    public function order_confirmed()
    {
        $combined_order = CombinedOrder::findOrFail(Session::get('combined_order_id'));

        Cart::where('user_id', $combined_order->user_id)
            ->delete();

        //Session::forget('club_point');
        //Session::forget('combined_order_id');

        foreach ($combined_order->orders as $order) {
            NotificationUtility::sendOrderPlacedNotification($order);
        }

        return view('frontend.order_confirmed', compact('combined_order'));
    }
}
